package com.yunhe.log.service.data.impl;

import com.yunhe.log.client.AuthorityClient;
import com.yunhe.common.model.PageParam;
import com.yunhe.log.domain.base.SystemMonitorLogType;
import com.yunhe.log.domain.data.SystemMonitorLog;
import com.yunhe.common.exception.ArgumentErrorException;
import com.yunhe.common.exception.ObjectNotFoundException;
import com.yunhe.common.exception.UniqueConstraintsException;
import com.yunhe.common.model.authority.User;
import com.yunhe.log.repository.data.SystemMonitorLogRepository;
import com.yunhe.log.service.base.SystemMonitorLogTypeService;
import com.yunhe.log.service.data.SystemMonitorLogService;
import com.yunhe.common.util.QueryUtil;
import com.yunhe.common.util.CollectionUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import java.sql.Time;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * 系统日志Service
 * @author liuronglei
 */
@Service
public class SystemMonitorLogServiceImpl implements SystemMonitorLogService {
    
    @Autowired
    private SystemMonitorLogRepository systemMonitorLogRepository;
    @Autowired
    private SystemMonitorLogTypeService systemMonitorLogTypeService;
    @Autowired
    private AuthorityClient authorityClient;

    private void processBeforeSave(SystemMonitorLog systemMonitorLog) {
        if (systemMonitorLog.getTypeId() != null) {
            SystemMonitorLogType type = systemMonitorLogTypeService.findById(systemMonitorLog.getTypeId());
            if(type != null){
                systemMonitorLog.setType(type.getTitle());
            }
        }
    }

    /**
     * 新增系统日志对象
     * @param systemMonitorLog 系统日志对象
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SystemMonitorLog createSystemMonitorLog(SystemMonitorLog systemMonitorLog)
            throws ArgumentErrorException, UniqueConstraintsException {
        processBeforeSave(systemMonitorLog);
        return systemMonitorLogRepository.save(systemMonitorLog);
    }

    /**
     * 批量新增系统日志对象
     * @param systemMonitorLogList 系统日志对象列表
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Iterable<SystemMonitorLog> createSystemMonitorLog(List<SystemMonitorLog> systemMonitorLogList)
            throws ArgumentErrorException, UniqueConstraintsException {
        for (SystemMonitorLog systemMonitorLog : systemMonitorLogList) {
            processBeforeSave(systemMonitorLog);
        }
        return systemMonitorLogRepository.saveAll(systemMonitorLogList);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteById(Long id) {
        systemMonitorLogRepository.deleteById(id);
    }

    /**
     * 更新系统日志
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SystemMonitorLog updateSystemMonitorLog(Long id,
                                                   Date date,
                                                   Time time,
                                                   Long typeId,
                                                   String type,
                                                   String content)
            throws ObjectNotFoundException {
        SystemMonitorLog systemMonitorLog = systemMonitorLogRepository.findById(id).orElse(null);
        if (systemMonitorLog == null) {
            throw new ObjectNotFoundException("找不到ID为" + id + "的日志记录");
        }
        Optional.ofNullable(date).ifPresent(systemMonitorLog::setDate);
        Optional.ofNullable(time).ifPresent(systemMonitorLog::setTime);
        Optional.ofNullable(typeId).ifPresent(systemMonitorLog::setTypeId);
        Optional.ofNullable(type).ifPresent(systemMonitorLog::setType);
        Optional.ofNullable(content).ifPresent(systemMonitorLog::setContent);
        processBeforeSave(systemMonitorLog);
        return systemMonitorLogRepository.save(systemMonitorLog);
    }

    /**
     * 更新系统日志
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SystemMonitorLog updateSystemMonitorLog(SystemMonitorLog systemMonitorLog)
            throws ObjectNotFoundException {
        boolean exists = systemMonitorLog.getId() != null && systemMonitorLogRepository.existsById(systemMonitorLog.getId());
        if (!exists) {
            throw new ObjectNotFoundException("找不到ID为" + systemMonitorLog.getId() + "的日志记录");
        }
        processBeforeSave(systemMonitorLog);
        return systemMonitorLogRepository.save(systemMonitorLog);
    }

    /**
     * 根据条件获得系统日志对象列表
     * @param dtime
     * @param time
     * @param typeId
     * @param typeTitle
     * @param content
     * @param pageParam 分页对象
     */
    @Override
    public Iterable<SystemMonitorLog> findSystemMonitorLogs(List<Date> dtime,
                                                            Time time,
                                                            List<Long> typeId,
                                                            String typeTitle,
                                                            String content,
                                                            PageParam pageParam) {
        if (pageParam.getSort() == null) {
            List<String> list = new ArrayList<>();
            list.add("-date");
            list.add("-time");
            pageParam.setSort(list);
        }
        Specification spec = (Specification<SystemMonitorLog>) (root, query, cb) -> {
            List<Predicate> criteria = new ArrayList<>();
            if (CollectionUtil.isNotEmpty(dtime)) {
                java.sql.Date start = new java.sql.Date(dtime.get(0).getTime());
                java.sql.Date end = new java.sql.Date(dtime.get(1).getTime());
                criteria.add(cb.and(cb.greaterThanOrEqualTo(root.get("date"), start),
                        cb.lessThanOrEqualTo(root.get("date"), end)));
            }
            if (time != null) {
                criteria.add(cb.equal(root.get("time"), time));
            }
            if (StringUtils.isNotEmpty(typeTitle)) {
                criteria.add(cb.equal(root.get("type"), typeTitle));
            }
            if (CollectionUtil.isNotEmpty(typeId)) {
                List<Long> list = typeId;
                if (list.size() == 1) {
                    criteria.add(cb.equal(root.get("typeId"), list.get(0)));
                } else if (list.size() == 2) {
                    criteria.add(cb.or(cb.equal(root.get("typeId"), list.get(0)),
                            cb.equal(root.get("typeId"), list.get(1))));
                } else if (list.size() == 3) {
                    criteria.add(cb.or(cb.equal(root.get("typeId"), list.get(0)),
                            cb.equal(root.get("typeId"), list.get(1)),
                            cb.equal(root.get("typeId"), list.get(2))));
                }
            }
            if (StringUtils.isNotEmpty(content)) {
                criteria.add(cb.equal(root.get("content"), content));
            }
            if (criteria.size() == 1) {
                query.where(criteria.get(0));
            } else {
                query.where(criteria.toArray(new Predicate[0]));
            }
            return null;
        };
        Iterable<SystemMonitorLog> result;
        if (QueryUtil.needPaging(pageParam)) {
            result = systemMonitorLogRepository.findAll(spec, QueryUtil.getPageRequest(pageParam));
        } else {
            result = systemMonitorLogRepository.findAll(spec, QueryUtil.getSort(pageParam.getSort()));
        }
        if (result == null) {
            result = new ArrayList<>();
        }
        return result;
    }

    @Override
    public SystemMonitorLog createExportRecord(Long firmCode, String menu, Long userId) {
        SystemMonitorLog systemMonitorLog = new SystemMonitorLog();
        systemMonitorLog.setStationId(firmCode);
        systemMonitorLog.setDate(new Date());
        systemMonitorLog.setTime(new Time(System.currentTimeMillis()));
        systemMonitorLog.setTypeId(3L);
        User user = authorityClient.getUserById(userId).getBody().getResults();
        String content = user.getTitle() + "在" + menu + "页面进行了导出操作";
        systemMonitorLog.setContent(content);
        processBeforeSave(systemMonitorLog);
        return systemMonitorLogRepository.save(systemMonitorLog);
    }
}
